﻿/*!
 * Knockout+ Library v1.1.0
 * https://knockoutplus.codeplex.com/
 *
 * Copyright 2014 Janusz Noszczyński and other contributors
 * Released under the MIT license
 * https://knockoutplus.codeplex.com/license
 *
 * More documentation and examples
 * http://blog.coderiseventures.com/
 */

(function ($, ko)
{
    function getIntValue(value, fallbackValue)
    {
        var val = parseInt(value);

        if (isNaN(val))
        {
            return fallbackValue;
        }
        else
        {
            return val;
        }
    }

    function getFloatValue(value, fallbackValue)
    {
        var val = parseFloat(value);

        if (isNaN(val))
        {
            return fallbackValue;
        }
        else
        {
            return val;
        }
    }

    function logToConsole(data)
    {
        if (window && window.console)
        {
            window.console.log(data);
        }
    }


    ko.bindingHandlers.trimmedValue =
    {
        init: function (element, valueAccessor)
        {
            var accessor = valueAccessor();
            var val = ko.utils.unwrapObservable(accessor);
            var $element = $(element);

            $element.change(function ()
            {
                var trimmed = $.trim($element.val());
                $(element).val(trimmed);
                accessor(trimmed);
            });
        },
        update: function (element, valueAccessor)
        {
            var accessor = valueAccessor();
            var val = ko.utils.unwrapObservable(accessor);
            var $element = $(element);

            var trimmed = $.trim(val);
            $(element).val(trimmed);
            accessor(trimmed);
        }
    };

    ko.bindingHandlers.intValue =
    {
        init: function (element, valueAccessor)
        {
            var accessor = valueAccessor();
            var fallbackValue = ko.utils.unwrapObservable(accessor.fallbackValue);
            var $element = $(element);

            $element.change(function ()
            {
                var intVal = getIntValue($element.val(), fallbackValue);
                accessor.value(intVal);
                $element.val(intVal);
            });
        },
        update: function (element, valueAccessor)
        {
            var accessor = valueAccessor();
            var val = ko.utils.unwrapObservable(accessor.value);
            var fallbackValue = ko.utils.unwrapObservable(accessor.fallbackValue);
            var $element = $(element);

            var intVal = getIntValue(val, fallbackValue);
            $element.val(intVal);
            accessor.value(intVal);
        }
    };

    ko.bindingHandlers.floatValue =
    {
        init: function (element, valueAccessor)
        {
            var accessor = valueAccessor();
            var fallbackValue = ko.utils.unwrapObservable(accessor.fallbackValue);
            var $element = $(element);

            $element.change(function ()
            {
                var intVal = getFloatValue($element.val(), fallbackValue);
                accessor.value(intVal);
                $element.val(intVal);
            });
        },
        update: function (element, valueAccessor)
        {
            var accessor = valueAccessor();
            var val = ko.utils.unwrapObservable(accessor.value);
            var fallbackValue = ko.utils.unwrapObservable(accessor.fallbackValue);
            var $element = $(element);

            var intVal = getFloatValue(val, fallbackValue);
            $element.val(intVal);
            accessor.value(intVal);
        }
    };

    ko.bindingHandlers.toggleSlide =
    {
        update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext)
        {
            var $element = $(element);
            var accessor = valueAccessor();
            var val = ko.utils.unwrapObservable(accessor);

            var enabled = value.enabled;
            var duration = value.duration ? value.duration : 400;

            if (enabled)
            {
                $element.slideUp(duration);
            }
            else
            {
                $element.slideDown(duration);
            }
        }
    };

    ko.bindingHandlers.trace =
    {
        init: function (element, valueAccessor, allBindings, viewModel, bindingContext)
        {
            var accessor = valueAccessor();
            var val = ko.utils.unwrapObservable(accessor);

            logToConsole("\r\n--------------------- " + "KO START TRACE: " + val + " ---------------------");

            logToConsole("\r\nelement:");
            logToConsole(element);

            logToConsole("\r\nvalueAccessor:");
            logToConsole(valueAccessor());

            logToConsole("\r\nallBindings:");
            logToConsole(allBindings());

            logToConsole("\r\nviewModel:");
            logToConsole(viewModel);

            logToConsole("\r\nbindingContext:");
            logToConsole(bindingContext);

            logToConsole("\r\n---------------------- " + "KO END TRACE: " + val + " ----------------------\r\n");
        }
    }

    ko.extenders.trace = function (target, value)
    {
        if (value)
        {
            target.subscribe(function (newValue)
            {
                logToConsole(value + newValue);
            });
        }

        return target;
    };

    ko.extenders.deferred = function (target, initialValue)
    {
        var internalObservable = ko.observable(initialValue);
        
        var setValue = function (result, value)
        {
            if (value && (typeof value.done == "function"))
            {
                result.inProgress(true);

                value.done(function (value)
                {
                    internalObservable(value);
                })
                .always(function ()
                {
                    result.inProgress(false);
                });
            }
            else
            {
                internalObservable(value);
            }
        }

        var result = ko.computed(
        {
            read: function ()
            {
                return internalObservable();
            },
            write: function (asyncValue)
            {
                setValue(result, asyncValue);
            }
        });

        result.inProgress = ko.observable(false);

        setValue(result, target());

        return result;
    };
})
(jQuery, ko);